package be.groept.ace.cursusplanning.model;

import java.util.*;

import be.groept.ace.cursusplanning.model.strategy.AangebodeCursussenSamenstellingsRegelsStrategy;
import be.groept.ace.cursusplanning.model.strategy.GroeptAangebodenCursussenSamenstellingRegelsStrategy;
import be.groept.ace.cursusplanning.persistency.IPersistentieController;
import be.groept.ace.cursusplanning.persistency.IPersistentieProvider;
import be.groept.ace.cursusplanning.persistency.Persisteerbaar;
import be.groept.ace.cursusplanning.utils.TijdsMoment1Dag;

/**
 * Klasse AangebodenCursus
 * @author Kevin Brigitta
 */

public class AangebodenCursus implements Comparable<AangebodenCursus>, Persisteerbaar{

	private Cursus cursus;
	private Lector lector;
	private int aantalPlaatsen;
	private Lokaal lokaal;
	private TijdsMoment1Dag tijdsMoment;
	private List<Inschrijving> inschrijvingen;
	
	private AangebodeCursussenSamenstellingsRegelsStrategy strategy;
	
	private IPersistentieProvider pProvider;

	/**
	 * Maakt een nieuw object "AangebodenCursus" aan
	 * @param cursus
	 * @param lector
	 * @param lokaal
	 * @param moment
	 * @param aantalPlaatsen
	 */
	public AangebodenCursus(Cursus cursus, Lector lector, Lokaal lokaal, TijdsMoment1Dag moment, Integer aantalPlaatsen){
		setLector(lector);
		setCursus(cursus);
		setAantalPlaatsen(aantalPlaatsen);
		setLokaal(lokaal);
		setTijdsMoment1Dag(moment);
		inschrijvingen = new ArrayList<Inschrijving>();
		
		strategy = new GroeptAangebodenCursussenSamenstellingRegelsStrategy();
	}
	
	public boolean magDeelnemenAanAangebodenCursus(Cursist cursist) {
		return strategy.magZichInschrijven(cursist, this);
	}
	
	/**
	 * geeft tijdsmoment terug wanneer de aangebodencursus gegeven wordt
	 * @return tijdsmoment
	 */
	public TijdsMoment1Dag getTijdsMoment1Dag() {
		return tijdsMoment;
	}
	
	private void setTijdsMoment1Dag (TijdsMoment1Dag moment) throws IllegalArgumentException{
		if(moment == null) throw new IllegalArgumentException("Tijdsmoment op 1 dag mag niet null zijn.");
		this.tijdsMoment = moment;
	}

	/**
	 * Geeft het aantal plaatsen beschikbaar voor die aangeboden cursus
	 * @return aantal plaatsen
	 */
	public int getAantalPlaatsen(){
		return this.aantalPlaatsen;
	}
	
	private void setAantalPlaatsen(int aantalPlaatsen) throws IllegalArgumentException{
		if(aantalPlaatsen < 1 ) throw new IllegalArgumentException("Aantal plaatsen moet groter zijn dan 0.");
		this.aantalPlaatsen = aantalPlaatsen;
	}
	
	public int getAantalInschrijvingen() {
		return getInschrijvingen().size();
	}
	
	/**
	 * Geeft lector terug die les geeft voor de aangeboden cursus
	 * @return lector
	 */
	public Lector getLector() {
		return lector;
	}
	
	/**
	 * Stelt een nieuwe waarde in voor lector
	 * @param lector
	 * @throws IllegalArgumentException
	 */
	private void setLector(Lector lector) throws IllegalArgumentException {
		if(lector == null) throw new IllegalArgumentException("Lector mag niet null zijn.");
		this.lector = lector;
	}
	
	/**
	 * Geeft het lokaal terug, waar er les gegeven wordt
	 * @return lokaal
	 */
	public Lokaal getLokaal() {
		return lokaal;
	}
	
	/**
	 * Stelt nieuwe waarde in voor lokaal
	 * @param lokaal
	 * @throws IllegalArgumentException
	 */
	private void setLokaal(Lokaal lokaal) throws IllegalArgumentException {
		if(lokaal == null) throw new IllegalArgumentException("Lokaal mag niet null zijn.");
		this.lokaal = lokaal;
	}
	
	public Cursus getCursus(){
		return this.cursus;
	}
	
	private void setCursus(Cursus cursus) throws IllegalArgumentException{
		if(cursus == null) throw new IllegalArgumentException("Cursus mag niet null zijn.");
		this.cursus = cursus;
	}
	
	
	
	/**
	 * Geeft alle inschrijvingen terug voor die aangeboden cursus
	 * @return inschrijvingen
	 */
	public List<Inschrijving> getInschrijvingen() {
		return inschrijvingen;
	}
	 
	/** 
	 * voegt een inschrijving voor de aangeboden cursus toe
	 * @param inschrijving
	 */
	public void addInschrijvingen(Inschrijving inschrijving) throws IllegalArgumentException{
		if(inschrijving == null) throw new IllegalArgumentException("inschrijving mag niet null zijn.");
		if(inschrijvingen.contains(inschrijving)) throw new IllegalArgumentException("Inschrijving is al geregistreerd.");
		this.inschrijvingen.add(inschrijving);
	}
	
	public void removeInschrijving(Inschrijving inschrijving) throws IllegalArgumentException{
		if(inschrijving == null) throw new IllegalArgumentException("inschrijving mag niet null zijn.");
		if(!inschrijvingen.contains(inschrijving)) throw new IllegalArgumentException("Inschrijving is niet geregistreerd in de aangebodencursus.");
		this.inschrijvingen.remove(inschrijving);
	}

	/**
	 * Eerst comparen op Cursus en dan op Lector en dan op TijdsMoment
	 */
	@Override
	public int compareTo(AangebodenCursus aangebodenCursus) {
		if(this.getCursus().compareTo(aangebodenCursus.getCursus()) == 0) {
			if(this.getLector().compareTo(aangebodenCursus.getLector()) == 0)
				return this.getTijdsMoment1Dag().compareTo(aangebodenCursus.getTijdsMoment1Dag());
			return this.getLector().compareTo(aangebodenCursus.getLector());
		}	
		return this.getCursus().compareTo(aangebodenCursus.getCursus());
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((cursus == null) ? 0 : cursus.hashCode());
		result = prime * result + ((lector == null) ? 0 : lector.hashCode());
		result = prime * result
				+ ((tijdsMoment == null) ? 0 : tijdsMoment.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		AangebodenCursus other = (AangebodenCursus) obj;
		if (cursus == null) {
			if (other.cursus != null)
				return false;
		} else if (!cursus.equals(other.cursus))
			return false;
		if (lector == null) {
			if (other.lector != null)
				return false;
		} else if (!lector.equals(other.lector))
			return false;
		if (tijdsMoment == null) {
			if (other.tijdsMoment != null)
				return false;
		} else if (!tijdsMoment.equals(other.tijdsMoment))
			return false;
		return true;
	}
	
	@Override
	public String toString() {
		return getCursus() + " gegeven door " + getLector();
	}

	@Override
	public Object[] getInfoToBeSaved(IPersistentieController Pcontroller) {
		
		return pProvider.getInfoToBeSaved(Pcontroller);
	}
	
	public IPersistentieProvider getPersistentieProvider(){
		return pProvider;
	}
	public void setPersistentieProvider(IPersistentieProvider provider){
		this.pProvider = provider;
	}


}
